package com.hyt.it.ogt.ykcj.service.exam.impl;

import com.hyt.it.ogt.ykcj.common.enums.CommonEnums;
import com.hyt.it.ogt.ykcj.common.enums.ExamFormEnums;
import com.hyt.it.ogt.ykcj.common.exception.CustomException;
import com.hyt.it.ogt.ykcj.common.utils.DateUtils;
import com.hyt.it.ogt.ykcj.common.utils.IdUtils;
import com.hyt.it.ogt.ykcj.common.utils.StringUtils;
import com.hyt.it.ogt.ykcj.domain.exam.EnterpriseExamScoreLineSetting;
import com.hyt.it.ogt.ykcj.domain.exam.EnterpriseExamScoreLineSettingSub;
import com.hyt.it.ogt.ykcj.domain.exam.ExamInfo;
import com.hyt.it.ogt.ykcj.domain.param.EnterpriseScoreLineListParam;
import com.hyt.it.ogt.ykcj.domain.param.EnterpriseScoreLineSaveParam;
import com.hyt.it.ogt.ykcj.domain.param.ScoreLineItem;
import com.hyt.it.ogt.ykcj.domain.vo.ExamInfoVo;
import com.hyt.it.ogt.ykcj.domain.vo.ExamSubjectVo;
import com.hyt.it.ogt.ykcj.mapper.exam.*;
import com.hyt.it.ogt.ykcj.service.exam.IEnterpriseExamScoreLineSettingService;
import com.hyt.it.ogt.ykcj.service.exam.IExamSubjectInfoService;
import com.hyt.it.ogt.ykcj.service.grade.IEnterpriseExamineeInfoService;
import com.hyt.it.ogt.ykcj.service.grade.IEnterpriseGroupExamineeInfoService;
import com.hyt.loginfo.service.IBaseLoginService;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @description: 分数线实现类
 * @author: longt
 * @date: 2021/11/23 下午9:28
 */
@Service
public class EnterpriseExamScoreLineSettingServiceImpl implements IEnterpriseExamScoreLineSettingService {

    private static final Logger log = LoggerFactory.getLogger(EnterpriseExamScoreLineSettingServiceImpl.class);

    @Autowired
    private EnterpriseExamScoreLineSettingMapper enterpriseExamScoreLineSettingMapper;

    @Autowired
    private EnterpriseExamScoreLineSettingSubMapper enterpriseExamScoreLineSettingSubMapper;

    @Autowired
    private IEnterpriseExamineeInfoService iEnterpriseExamineeInfoService;

    @Autowired
    private IExamSubjectInfoService iExamSubjectInfoService;

    @Autowired
    private ExamInfoMapper examInfoMapper;

    @Autowired
    private ExamSubjectInfoMapper examSubjectInfoMapper;

    @Autowired
    private ExamSubjectNameConfigMapper examSubjectNameConfigMapper;

    @Autowired
    private ExamNameConfigMapper examNameConfigMapper;

    @Autowired
    private IBaseLoginService iBaseLoginService;

    @Autowired
    private IEnterpriseGroupExamineeInfoService enterpriseGroupExamineeInfoService;

    @Autowired
    private IEnterpriseExamScoreLineSettingService iEnterpriseExamScoreLineSettingService;

    @Autowired
    private IEnterpriseExamScoreLineSettingService enterpriseExamScoreLineSettingService;

    @Resource(name = "threadPoolTaskExecutor")
    ThreadPoolTaskExecutor threadPoolTaskExecutor;

    /**
     * 分数线最大条数
     */
    private static final int SCORELINE_MAX_COUNT = 10;

    @Override
    @Transactional(rollbackFor = {RuntimeException.class})
    public void createScoreLineBatch(EnterpriseScoreLineListParam enterpriseScoreLineListParam) {
        List<EnterpriseScoreLineSaveParam> scoreLineData = enterpriseScoreLineListParam.getScoreLineData();
        // 判断校验 0:单科为更新不会重复  1，2有可能重复
        if (!CommonEnums.SCORE_LINE_TYPE_0.getCode().equals(enterpriseScoreLineListParam.getType())) {
            // 判断条数
            this.checkScoreLineCount(enterpriseScoreLineListParam);
            // 判断重复
            this.checkScoreLineRepeat(enterpriseScoreLineListParam);
        }

        for (EnterpriseScoreLineSaveParam scoreLine : scoreLineData) {
            // 区间分数线的特殊处理
            if (CommonEnums.SCORE_LINE_TYPE_2.getCode().equals(scoreLine.getType())) {
                List<String> subjectIdList = enterpriseScoreLineListParam.getSubjectList();
                List<String> examList = enterpriseScoreLineListParam.getExamList();
                List<ScoreLineItem> scoreLineItems = new ArrayList<>();
                if (subjectIdList != null) {
                    for (String subjectId : subjectIdList) {
                        ScoreLineItem scoreLineItem = new ScoreLineItem();
                        scoreLineItem.setSettingId(scoreLine.getId());
                        scoreLineItem.setSubjectId(subjectId);
                        scoreLineItem.setRegionName(scoreLine.getRegionName());
                        scoreLineItem.setRegionStartScore(scoreLine.getRegionStartScore());
                        scoreLineItem.setRegionEndScore(scoreLine.getRegionEndScore());
                        scoreLineItems.add(scoreLineItem);
                    }
                }
                if (examList != null) {
                    for (String examId : examList) {
                        ScoreLineItem scoreLineItem = new ScoreLineItem();
                        scoreLineItem.setSettingId(scoreLine.getId());
                        scoreLineItem.setExamId(examId);
                        scoreLineItem.setRegionName(scoreLine.getRegionName());
                        scoreLineItem.setRegionStartScore(scoreLine.getRegionStartScore());
                        scoreLineItem.setRegionEndScore(scoreLine.getRegionEndScore());
                        scoreLineItems.add(scoreLineItem);
                    }
                }
                scoreLine.setScoreLineItems(scoreLineItems);
            }
            // 设置type
            scoreLine.setType(enterpriseScoreLineListParam.getType());
            createScoreLine(scoreLine);
            enterpriseScoreLineListParam.setExamId(scoreLine.getExamId());
            enterpriseScoreLineListParam.setDimension(scoreLine.getDimension());
        }

        this.gradeStatusSync(enterpriseScoreLineListParam.getExamId(), enterpriseScoreLineListParam.getDimension());
    }

    @Override
    public void gradeStatusSync(String examId, String dimension) {
        // 异步调用同步成绩是否合格
        log.info(StringUtils.format("开始异步调用成绩是否合格,examId:{},dimension:{}", examId, dimension));
        threadPoolTaskExecutor.submit(new SyncExamineeInfoTask(examId, dimension));
    }

    @Override
    public void addToScoreLine(EnterpriseScoreLineSaveParam enterpriseScoreLineSaveParam) {
        if (CommonEnums.SCORE_LINE_TYPE_1.getCode().equals(enterpriseScoreLineSaveParam.getType()) &&
                CommonEnums.SCORE_LINE_DIMENSION_0.getCode().equals(enterpriseScoreLineSaveParam.getDimension())) {
            // 查询原有分数线
            List<ScoreLineItem> scoreLineItems = enterpriseExamScoreLineSettingSubMapper.selectEnterpriseExamScoreLineSettingByExamId(enterpriseScoreLineSaveParam.getExamId());

            List<ScoreLineItem> scoreLineItemsNew = enterpriseScoreLineSaveParam.getScoreLineItems();
            Map<String, ScoreLineItem> newMap = scoreLineItemsNew.stream().collect(Collectors.toMap(ScoreLineItem::getSubjectId, ScoreLineItem -> ScoreLineItem));

            // 对已有科目进行更新
            for (ScoreLineItem scoreLineItem : scoreLineItems) {
                if (null != newMap.get(scoreLineItem.getSubjectId())) {
                    ScoreLineItem scoreLineItemNew = newMap.get(scoreLineItem.getSubjectId());
                    scoreLineItem.setScore(scoreLineItemNew.getScore());
                    scoreLineItemsNew.remove(scoreLineItemNew);
                }
            }

            scoreLineItemsNew.addAll(scoreLineItems);
            enterpriseScoreLineSaveParam.setId(scoreLineItems.get(0).getSettingId());
            enterpriseScoreLineSaveParam.setCompositeScore(enterpriseScoreLineSaveParam.getCompositeScore());

            //更新
            this.saveOrUpdate(enterpriseScoreLineSaveParam);
        }

        if (CommonEnums.SCORE_LINE_TYPE_1.getCode().equals(enterpriseScoreLineSaveParam.getType()) &&
                CommonEnums.SCORE_LINE_DIMENSION_2.getCode().equals(enterpriseScoreLineSaveParam.getDimension())) {
            // 查询原有分数线
            List<ScoreLineItem> scoreLineItems = enterpriseExamScoreLineSettingSubMapper.selectEnterpriseExamScoreLineSettingByExamId(enterpriseScoreLineSaveParam.getExamId());

            List<ScoreLineItem> scoreLineItemsNew = enterpriseScoreLineSaveParam.getScoreLineItems();
            Map<String, ScoreLineItem> newMap = scoreLineItemsNew.stream().collect(Collectors.toMap(ScoreLineItem::getExamId, ScoreLineItem -> ScoreLineItem));

            // 对已有子考试进行更新
            for (ScoreLineItem scoreLineItem : scoreLineItems) {
                if (null != newMap.get(scoreLineItem.getExamId())) {
                    ScoreLineItem scoreLineItemNew = newMap.get(scoreLineItem.getExamId());
                    scoreLineItem.setScore(scoreLineItemNew.getScore());
                    scoreLineItemsNew.remove(scoreLineItemNew);
                }
            }

            scoreLineItemsNew.addAll(scoreLineItems);
            enterpriseScoreLineSaveParam.setId(scoreLineItems.get(0).getSettingId());
            enterpriseScoreLineSaveParam.setCompositeScore(enterpriseScoreLineSaveParam.getCompositeScore());

            //更新
            this.saveOrUpdate(enterpriseScoreLineSaveParam);
        }
    }

    /**
     * 判断条数
     *
     * @param enterpriseScoreLineListParam
     */
    private void checkScoreLineCount(EnterpriseScoreLineListParam enterpriseScoreLineListParam) {
        String type = enterpriseScoreLineListParam.getType();
        List<EnterpriseScoreLineSaveParam> scoreLineData = enterpriseScoreLineListParam.getScoreLineData();
        scoreLineData = scoreLineData.stream().filter(item -> CommonEnums.DATA_DEL_FLAG_N.getCode().equals(item.getDelFlag())).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(scoreLineData) && SCORELINE_MAX_COUNT < scoreLineData.size()) {
            if (CommonEnums.SCORE_LINE_TYPE_1.getCode().equals(type)) {
                throw new CustomException(StringUtils.format("分数线条数不能超过{}条！", SCORELINE_MAX_COUNT));
            }
            if (CommonEnums.SCORE_LINE_TYPE_2.getCode().equals(type)) {
                throw new CustomException(StringUtils.format("区间设置项不允许超过{}条！", SCORELINE_MAX_COUNT));
            }
        }
    }

    /**
     * 判重
     *
     * @param enterpriseScoreLineListParam
     */
    private void checkScoreLineRepeat(EnterpriseScoreLineListParam enterpriseScoreLineListParam) {
        List<EnterpriseScoreLineSaveParam> scoreLineData = enterpriseScoreLineListParam.getScoreLineData();
        // 区间分数线名称不能相同
        if (CommonEnums.SCORE_LINE_TYPE_2.getCode().equals(enterpriseScoreLineListParam.getType())) {
            List<String> regionNameDistinctList = scoreLineData.stream().map(EnterpriseScoreLineSaveParam::getRegionName).distinct().collect(Collectors.toList());
            if (scoreLineData.size() > regionNameDistinctList.size()) {
                throw new CustomException(StringUtils.format("区间名称不能相同，请重新设置！"));
            }
        }

        // 区间分数线判重合，复合分数线判冲突
        for (EnterpriseScoreLineSaveParam item1 : scoreLineData) {
            // 跳过删除的
            if (CommonEnums.DATA_DEL_FLAG_D.getCode().equals(item1.getDelFlag())) {
                continue;
            }
            for (EnterpriseScoreLineSaveParam item2 : scoreLineData) {
                // 跳过删除的
                if (item1.equals(item2) || CommonEnums.DATA_DEL_FLAG_D.getCode().equals(item2.getDelFlag())) {
                    continue;
                }
                if (CommonEnums.SCORE_LINE_TYPE_1.getCode().equals(item2.getType())) {
                    this.ifCoincideomposite(item1, item2);
                }
                if (CommonEnums.SCORE_LINE_TYPE_2.getCode().equals(item2.getType())) {
                    this.ifCoincideRegion(item1, item2);
                }
            }
        }
    }

    /**
     * 两条是否为冲突复合分数线
     *
     * @return
     */
    public void ifCoincideomposite(EnterpriseScoreLineSaveParam item1, EnterpriseScoreLineSaveParam item2) {
        List<ScoreLineItem> scoreLineItems1 = item1.getScoreLineItems();
        List<ScoreLineItem> scoreLineItems2 = item2.getScoreLineItems();
        String subjectIds1 = "";
        String subjectIds2 = "";
        for (ScoreLineItem scoreLineItem : scoreLineItems1) {
            subjectIds1 = StringUtils.join(subjectIds1, scoreLineItem.getSubjectId());
        }
        for (ScoreLineItem scoreLineItem : scoreLineItems2) {
            subjectIds2 = StringUtils.join(subjectIds2, scoreLineItem.getSubjectId());
        }
        if (StringUtils.isNotEmpty(subjectIds1) && StringUtils.isNotEmpty(subjectIds2)
                && subjectIds1.equals(subjectIds2)) {
            throw new CustomException(StringUtils.format("分数线冲突，请重新设置！"));
        }
    }


    /**
     * 返回两条是否冲突区间分数线
     *
     * @return
     */
    public void ifCoincideRegion(EnterpriseScoreLineSaveParam item1, EnterpriseScoreLineSaveParam item2) {
        // 最小值为空则为0
        if (StringUtils.isEmpty(item1.getRegionStartScore())) {
            item1.setRegionStartScore(String.valueOf(BigDecimal.ZERO));
        }
        if (StringUtils.isEmpty(item2.getRegionStartScore())) {
            item2.setRegionStartScore(String.valueOf(BigDecimal.ZERO));
        }

        // 最大值为空则为科目总分
        if (StringUtils.isEmpty(item1.getRegionEndScore())) {
            item1.setRegionEndScore(String.valueOf(new BigDecimal(999999)));
        }
        if (StringUtils.isEmpty(item2.getRegionEndScore())) {
            item2.setRegionEndScore(String.valueOf(new BigDecimal(999999)));
        }

        // 判断区间是否有重合
        BigDecimal regionStartScore1 = new BigDecimal(item1.getRegionStartScore());
        BigDecimal regionEndScore1 = new BigDecimal(item1.getRegionEndScore());
        BigDecimal regionStartScore2 = new BigDecimal(item2.getRegionStartScore());
        BigDecimal regionEndScore2 = new BigDecimal(item2.getRegionEndScore());

        // 分数线2的最小值在分数线1区间中
        if (regionStartScore2.compareTo(regionStartScore1) > 0
                && regionStartScore2.compareTo(regionEndScore1) < 0) {
            throw new CustomException(StringUtils.format("{}区间值与{}区间值有重合，请重新设置", item1.getRegionName(), item2.getRegionName()));
        }

        // 分数线2的最大值在分数线1区间中
        if (regionEndScore2.compareTo(regionStartScore1) > 0
                && regionEndScore2.compareTo(regionEndScore1) < 0) {
            throw new CustomException(StringUtils.format("{}区间值与{}区间值有重合，请重新设置", item1.getRegionName(), item2.getRegionName()));
        }

        // 同上
        if (regionStartScore1.compareTo(regionStartScore2) > 0
                && regionStartScore1.compareTo(regionEndScore2) < 0) {
            throw new CustomException(StringUtils.format("{}区间值与{}区间值有重合，请重新设置", item1.getRegionName(), item2.getRegionName()));
        }

        // 同上
        if (regionEndScore1.compareTo(regionStartScore2) > 0
                && regionEndScore1.compareTo(regionEndScore2) < 0) {
            throw new CustomException(StringUtils.format("{}区间值与{}区间值有重合，请重新设置", item1.getRegionName(), item2.getRegionName()));
        }
    }


    @Override
    @Transactional(rollbackFor = {RuntimeException.class})
    public void createScoreLine(EnterpriseScoreLineSaveParam enterpriseScoreLineSaveParam) {
        // 分数线列表不能为空
        if (!CommonEnums.SCORE_LINE_TYPE_2.getCode().equals(enterpriseScoreLineSaveParam.getType())
                && CollectionUtils.isEmpty(enterpriseScoreLineSaveParam.getScoreLineItems())) {
            throw new CustomException("分数线列表不能为空");
        }

        // 已归档考试不允许修改分数线
        iEnterpriseExamineeInfoService.checkExamineeArchived(enterpriseScoreLineSaveParam.getExamId());

        // 插入
        saveOrUpdate(enterpriseScoreLineSaveParam);
    }

    /**
     * 批量保存
     *
     * @param enterpriseExamInsertParamList
     */
    @Override
    @Transactional(rollbackFor = {RuntimeException.class})
    public void saveBatch(List<EnterpriseScoreLineSaveParam> enterpriseExamInsertParamList) {
        for (EnterpriseScoreLineSaveParam enterpriseScoreLineSaveParam : enterpriseExamInsertParamList) {
            // 复合分数线有需要删除的直接删除
            if (CommonEnums.SCORE_LINE_TYPE_1.getCode().equals(enterpriseScoreLineSaveParam.getType()) &&
                    CommonEnums.DATA_DEL_FLAG_D.getCode().equals(enterpriseScoreLineSaveParam.getDelFlag())) {
                enterpriseExamScoreLineSettingMapper.deleteEnterpriseExamScoreLineSettingById(enterpriseScoreLineSaveParam.getId());
                continue;
            }
            saveOrUpdate(enterpriseScoreLineSaveParam);
        }
    }

    /**
     * 新增修改数据库
     *
     * @param enterpriseScoreLineSaveParam
     */
    private void saveOrUpdate(EnterpriseScoreLineSaveParam enterpriseScoreLineSaveParam) {
        if (CommonEnums.DATA_DEL_FLAG_D.getCode().equals(enterpriseScoreLineSaveParam.getDelFlag())) {
            enterpriseExamScoreLineSettingMapper.deleteEnterpriseExamScoreLineSettingById(enterpriseScoreLineSaveParam.getId());
            return;
        }

        // 三种类型互斥，先删除其他类型的数据
        this.deleteScoreLineByType(enterpriseScoreLineSaveParam);

        // 插入分数线表
        EnterpriseExamScoreLineSetting scoreLineSetting = new EnterpriseExamScoreLineSetting();
        scoreLineSetting.setUpdateBy(iBaseLoginService.getSysUser().getName());
        scoreLineSetting.setUpdateTime(DateUtils.getNowDate());
        scoreLineSetting.setExamId(enterpriseScoreLineSaveParam.getExamId());
        scoreLineSetting.setId(enterpriseScoreLineSaveParam.getId());
        scoreLineSetting.setComposite(enterpriseScoreLineSaveParam.getType());
        scoreLineSetting.setDimension(enterpriseScoreLineSaveParam.getDimension());
        if (StringUtils.isEmpty(enterpriseScoreLineSaveParam.getId())) {
            scoreLineSetting.setId(IdUtils.generateId());
            scoreLineSetting.setCreateBy(iBaseLoginService.getSysUser().getName());
            scoreLineSetting.setCreateTime(DateUtils.getNowDate());
            enterpriseExamScoreLineSettingMapper.insertEnterpriseExamScoreLineSetting(scoreLineSetting);
        } else {
            enterpriseExamScoreLineSettingMapper.updateEnterpriseExamScoreLineSetting(scoreLineSetting);
        }

        // 插入分数线明细表
        enterpriseExamScoreLineSettingSubMapper.deleteEnterpriseExamScoreLineSettingSubBySettingId(enterpriseScoreLineSaveParam.getId());
        List<EnterpriseExamScoreLineSettingSub> saveScoreList = new ArrayList<>();
        List<ScoreLineItem> scoreLineItems = enterpriseScoreLineSaveParam.getScoreLineItems();

        // 校验满分
        BigDecimal fullScore;
        if (!CommonEnums.SCORE_LINE_DIMENSION_2.getCode().equals(enterpriseScoreLineSaveParam.getDimension())) {
            fullScore = scoreLineFullCompareCheckSubject(enterpriseScoreLineSaveParam);
        } else {
            fullScore = scoreLineFullCompareCheckExam(enterpriseScoreLineSaveParam);
        }

        // 保存
        for (ScoreLineItem scoreLineItem : scoreLineItems) {
            EnterpriseExamScoreLineSettingSub scoreLineSettingSub = new EnterpriseExamScoreLineSettingSub();
            scoreLineSettingSub.setId(IdUtils.generateId());
            scoreLineSettingSub.setCreateBy(iBaseLoginService.getSysUser().getName());
            scoreLineSettingSub.setCreateTime(DateUtils.getNowDate());
            scoreLineSettingSub.setUpdateBy(iBaseLoginService.getSysUser().getName());
            scoreLineSettingSub.setUpdateTime(DateUtils.getNowDate());
            scoreLineSettingSub.setEnterpriseExamScoreLineSettingId(scoreLineSetting.getId());

            if (!CommonEnums.SCORE_LINE_DIMENSION_2.getCode().equals(enterpriseScoreLineSaveParam.getDimension())) {
                // 考试下的科目id
                scoreLineSettingSub.setSubjectId(scoreLineItem.getSubjectId());
            } else {
                // 考试组分数线下的子考试id
                scoreLineSettingSub.setExamId(scoreLineItem.getExamId());
            }

            // 特殊处理
            if (CommonEnums.SCORE_LINE_TYPE_0.getCode().equals(enterpriseScoreLineSaveParam.getType())) {
                // 业务数据
                scoreLineSettingSub.setScore(new BigDecimal(scoreLineItem.getScore()));
                scoreLineSettingSub.setComparisonType(scoreLineItem.getComparisonType());
            } else if (CommonEnums.SCORE_LINE_TYPE_1.getCode().equals(enterpriseScoreLineSaveParam.getType())) {
                if (StringUtils.isEmpty(enterpriseScoreLineSaveParam.getComparisonType())
                        || StringUtils.isEmpty(enterpriseScoreLineSaveParam.getCompositeScore())) {
                    throw new CustomException("复合分数线不能为空！");
                }
                scoreLineSettingSub.setComparisonType(enterpriseScoreLineSaveParam.getComparisonType());
                scoreLineSettingSub.setScore(new BigDecimal(enterpriseScoreLineSaveParam.getCompositeScore()));
            } else if (CommonEnums.SCORE_LINE_TYPE_2.getCode().equals(enterpriseScoreLineSaveParam.getType())) {
                scoreLineSettingSub.setRegionName(scoreLineItem.getRegionName());
                scoreLineSettingSub.setRegionStartScore(new BigDecimal(scoreLineItem.getRegionStartScore()));
                scoreLineSettingSub.setRegionEndScore(new BigDecimal(scoreLineItem.getRegionEndScore()));

                BigDecimal startDecimal = new BigDecimal(scoreLineItem.getRegionStartScore());
                scoreLineSettingSub.setRegionStartScore(startDecimal);
                BigDecimal endDecimal = new BigDecimal(scoreLineItem.getRegionEndScore());
                scoreLineSettingSub.setRegionEndScore(endDecimal);
                // 区间设置满分值的时候加一
                if (endDecimal.compareTo(fullScore) == 0) {
                    scoreLineSettingSub.setRegionEndScore(endDecimal.add(new BigDecimal(1)));
                }
            }
            saveScoreList.add(scoreLineSettingSub);
        }
        enterpriseExamScoreLineSettingSubMapper.insertBatchEnterpriseExamScoreLineSettingSub(saveScoreList);
    }

    /**
     * 分数线与试卷满分比较
     */
    private BigDecimal scoreLineFullCompareCheckSubject(EnterpriseScoreLineSaveParam enterpriseScoreLineSaveParam) {
        List<ScoreLineItem> scoreLineItems = enterpriseScoreLineSaveParam.getScoreLineItems();
        // 获取试卷总分
        Map<String, BigDecimal> fullScoreMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(scoreLineItems)) {
            String[] ids = scoreLineItems.stream().map(item -> item.getSubjectId()).toArray(String[]::new);
            List<ExamSubjectVo> examSubjectVos = iExamSubjectInfoService.selectExamSubjectListByIds(ids);
            for (ExamSubjectVo examSubjectVo : examSubjectVos) {
                if (null != examSubjectVo.getPaperFullMarks()) {
                    fullScoreMap.put(examSubjectVo.getSubjectId(), examSubjectVo.getPaperFullMarks());
                }
            }
        }
        // 和分数线比较
        BigDecimal stemMarks = new BigDecimal(0);
        for (ScoreLineItem scoreLineItem : scoreLineItems) {
            BigDecimal fullScore = fullScoreMap.get(scoreLineItem.getSubjectId());
            if (null == fullScore) {
                fullScore = BigDecimal.ZERO;
            }
            if (CommonEnums.SCORE_LINE_TYPE_0.getCode().equals(enterpriseScoreLineSaveParam.getType())) {
                String score = scoreLineItem.getScore();
                // 判断数值
                if (new BigDecimal(score).compareTo(BigDecimal.ZERO) < 0) {
                    throw new CustomException("分数线不能小于0！");
                }
                if (CommonEnums.COMPARISON_TYPE_0.getCode().equals(scoreLineItem.getComparisonType())
                        && new BigDecimal(score).compareTo(fullScore) > -1) {
                    throw new CustomException("科目分数线必须小于试卷满分！");
                }
                if (CommonEnums.COMPARISON_TYPE_1.getCode().equals(scoreLineItem.getComparisonType())
                        && new BigDecimal(score).compareTo(fullScore) > 0) {
                    throw new CustomException("科目分数线必须小于等于试卷满分！");
                }
            } else {
                stemMarks = stemMarks.add(fullScore);
                continue;
            }
        }
        // 复合分数线
        if (CommonEnums.SCORE_LINE_TYPE_1.getCode().equals(enterpriseScoreLineSaveParam.getType())) {
            if (new BigDecimal(enterpriseScoreLineSaveParam.getCompositeScore()).compareTo(BigDecimal.ZERO) < 0) {
                throw new CustomException("分数线不能小于0！");
            }
            if (CommonEnums.COMPARISON_TYPE_0.getCode().equals(enterpriseScoreLineSaveParam.getComparisonType())
                    && new BigDecimal(enterpriseScoreLineSaveParam.getCompositeScore()).compareTo(stemMarks) > -1) {
                throw new CustomException("复合分数线必须小于试卷满分总和！");
            }
            if (CommonEnums.COMPARISON_TYPE_1.getCode().equals(enterpriseScoreLineSaveParam.getComparisonType())
                    && new BigDecimal(enterpriseScoreLineSaveParam.getCompositeScore()).compareTo(stemMarks) > 0) {
                throw new CustomException("复合分数线必须小于等于试卷满分总和！");
            }
        }
        // 区间分数线
        if (CommonEnums.SCORE_LINE_TYPE_2.getCode().equals(enterpriseScoreLineSaveParam.getType())) {
            if (new BigDecimal(enterpriseScoreLineSaveParam.getRegionStartScore()).compareTo(BigDecimal.ZERO) < 0) {
                throw new CustomException("分数线不能小于0！");
            }
            if (new BigDecimal(enterpriseScoreLineSaveParam.getRegionEndScore()).subtract(new BigDecimal(1)).compareTo(stemMarks) > 0) {
                throw new CustomException(StringUtils.format("{}的区间值不能超过总分！", enterpriseScoreLineSaveParam.getRegionName()));
            }
            if (new BigDecimal(enterpriseScoreLineSaveParam.getRegionStartScore()).compareTo(new BigDecimal(enterpriseScoreLineSaveParam.getRegionEndScore())) > 0) {
                throw new CustomException(StringUtils.format("{}的区间值不允许设置空值！", enterpriseScoreLineSaveParam.getRegionName()));
            }
        }

        return stemMarks;
    }


    /**
     * 分数线与考试组试卷满分比较
     */
    private BigDecimal scoreLineFullCompareCheckExam(EnterpriseScoreLineSaveParam enterpriseScoreLineSaveParam) {
        List<ScoreLineItem> scoreLineItems = enterpriseScoreLineSaveParam.getScoreLineItems();
        // 获取试卷总分
        Map<String, BigDecimal> fullScoreMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(scoreLineItems)) {
            // 获取考试组下所有的考试
            String[] ids = scoreLineItems.stream().map(item -> item.getExamId()).toArray(String[]::new);
            List<ExamSubjectVo> examSubjectVos = iExamSubjectInfoService.selectExamSubjectListByExamIds(ids);
            fullScoreMap = examSubjectVos.stream().collect(Collectors.groupingBy(ExamSubjectVo::getExamInfoId, Collectors.reducing(BigDecimal.ZERO,
                    ExamSubjectVo::getPaperFullMarks, BigDecimal::add)));
        }
        // 和分数线比较
        BigDecimal stemMarks = new BigDecimal(0);
        for (ScoreLineItem scoreLineItem : scoreLineItems) {
            BigDecimal fullScore = fullScoreMap.get(scoreLineItem.getExamId());
            if (CommonEnums.SCORE_LINE_TYPE_0.getCode().equals(enterpriseScoreLineSaveParam.getType())) {
                String score = scoreLineItem.getScore();
                // 判断数值
                if (new BigDecimal(score).compareTo(BigDecimal.ZERO) < 0) {
                    throw new CustomException("分数线不能小于0！");
                }
                if (CommonEnums.COMPARISON_TYPE_0.getCode().equals(scoreLineItem.getComparisonType())
                        && new BigDecimal(score).compareTo(fullScore) > -1) {
                    throw new CustomException("子考试分数线必须小于考试满分！");
                }
                if (CommonEnums.COMPARISON_TYPE_1.getCode().equals(scoreLineItem.getComparisonType())
                        && new BigDecimal(score).compareTo(fullScore) > 0) {
                    throw new CustomException("子考试分数线必须小于等于考试满分！");
                }
            } else {
                stemMarks = stemMarks.add(fullScore);
                continue;
            }
        }
        // 复合分数线
        if (CommonEnums.SCORE_LINE_TYPE_1.getCode().equals(enterpriseScoreLineSaveParam.getType())) {
            if (new BigDecimal(enterpriseScoreLineSaveParam.getCompositeScore()).compareTo(BigDecimal.ZERO) < 0) {
                throw new CustomException("分数线不能小于0！");
            }
            if (CommonEnums.COMPARISON_TYPE_0.getCode().equals(enterpriseScoreLineSaveParam.getComparisonType())
                    && new BigDecimal(enterpriseScoreLineSaveParam.getCompositeScore()).compareTo(stemMarks) > -1) {
                throw new CustomException("复合分数线必须小于考试满分总和！");
            }
            if (CommonEnums.COMPARISON_TYPE_1.getCode().equals(enterpriseScoreLineSaveParam.getComparisonType())
                    && new BigDecimal(enterpriseScoreLineSaveParam.getCompositeScore()).compareTo(stemMarks) > 0) {
                throw new CustomException("复合分数线必须小于等于考试满分总和！");
            }
        }
        // 区间分数线
        if (CommonEnums.SCORE_LINE_TYPE_2.getCode().equals(enterpriseScoreLineSaveParam.getType())) {
            if (new BigDecimal(enterpriseScoreLineSaveParam.getRegionStartScore()).compareTo(BigDecimal.ZERO) < 0) {
                throw new CustomException("分数线不能小于0！");
            }
            if (new BigDecimal(enterpriseScoreLineSaveParam.getRegionEndScore()).subtract(new BigDecimal(1)).compareTo(stemMarks) > 0) {
                throw new CustomException(StringUtils.format("{}的区间值不能超过总分！", enterpriseScoreLineSaveParam.getRegionName()));
            }
            if (new BigDecimal(enterpriseScoreLineSaveParam.getRegionStartScore()).compareTo(new BigDecimal(enterpriseScoreLineSaveParam.getRegionEndScore())) > 0) {
                throw new CustomException(StringUtils.format("{}的区间值不允许设置空值！", enterpriseScoreLineSaveParam.getRegionName()));
            }
        }

        return stemMarks;
    }

    /**
     * 异步调用重新计算合格不合格的接口
     */
    public class SyncExamineeInfoTask implements Runnable {
        private String examId;
        private String dimension;

        public SyncExamineeInfoTask(String examId, String dimension) {
            this.examId = examId;
            this.dimension = dimension;
        }

        @Override
        public void run() {
            ExamInfo examInfo = examInfoMapper.selectExamInfoById(examId);
//            List<EnterpriseScoreLineSaveParam> scoreLineSettings = enterpriseExamScoreLineSettingService.getScoreLineList(examId, null, null);
            // 上来就先休息2秒，确保分数线已经保存成功了，再修改合格标志。数据库还未插入成功，线程休息一下
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                log.error("线程休眠异常", e);
                Thread.currentThread().interrupt();
            }

            if (ExamFormEnums.FORM_EXAM_GROUP.getCode().equals(examInfo.getExamForm())) {
                log.info(StringUtils.format(" 异步调用线程(考试组),examId:{},dimension:{}", examId, dimension));
                if (Integer.valueOf(CommonEnums.EXAM_MERGE_TYPE_1.getCode()).equals(examInfo.getMergeType()) && CommonEnums.SCORE_LINE_DIMENSION_1.getCode().equals(dimension)) {
                    iEnterpriseExamineeInfoService.refreshEnterpriseExamineeSubjectQualified(examId);
                } else {
                    Map<String, Object> parms = new HashMap<>();
                    parms.put("relationId", examId);
                    List<ExamInfoVo> examInfoVos = examInfoMapper.selectEnterpriseExamInfoByParms(parms);
                    List<String> relationExamIds = examInfoVos.stream()
                            .map(ExamInfoVo::getId)
                            .collect(Collectors.toList());
                    enterpriseGroupExamineeInfoService.refreshExamExamineeQualified(relationExamIds, examId);
                }
            } else {
                log.info(StringUtils.format(" 异步调用线程(考试),examId:{},dimension:{}", examId, dimension));
                if (CommonEnums.SCORE_LINE_DIMENSION_0.getCode().equals(dimension)) {
                    iEnterpriseExamineeInfoService.refreshEnterpriseExamineeQualified(examId);
                } else if (CommonEnums.SCORE_LINE_DIMENSION_1.getCode().equals(dimension)) {
                    iEnterpriseExamineeInfoService.refreshEnterpriseExamineeSubjectQualified(examId);
                } else if (CommonEnums.SCORE_LINE_DIMENSION_2.getCode().equals(dimension)) {
                    // TODO 调用计算合不合格
                } else {
                    iEnterpriseExamineeInfoService.refreshEnterpriseExamineeQualified(examId);
                    iEnterpriseExamineeInfoService.refreshEnterpriseExamineeSubjectQualified(examId);
                }
            }
        }
    }

    /**
     * 根据考试id，维度，科目查询分数线信息
     *
     * @param examId
     * @param dimension ""则查全部，0查考试，1查科目
     * @param subjectId
     * @return
     */
    @Override
    public List<EnterpriseScoreLineSaveParam> getScoreLineList(String examId, String dimension, String subjectId) {
        List<EnterpriseScoreLineSaveParam> result = new ArrayList<>();
        // 如果科目id不为空则认为是科目维度
        if (StringUtils.isEmpty(dimension) && StringUtils.isNotEmpty(subjectId)) {
            dimension = CommonEnums.SCORE_LINE_DIMENSION_1.getCode();
        }

        // 查询分数线
        EnterpriseExamScoreLineSetting settingQuery = new EnterpriseExamScoreLineSetting();
        settingQuery.setExamId(examId);
        if (StringUtils.isNotEmpty(dimension)) {
            settingQuery.setDimension(dimension);
        }

        List<EnterpriseExamScoreLineSetting> enterpriseExamScoreLineSettings = enterpriseExamScoreLineSettingMapper.selectEnterpriseExamScoreLineSettingList(settingQuery);
        // 根据考试id查询所有分数线明细
        List<ScoreLineItem> scoreDetailListAll = enterpriseExamScoreLineSettingSubMapper.selectEnterpriseExamScoreLineSettingByExamId(examId);

        Map<String, List<ScoreLineItem>> detailMap = scoreDetailListAll.stream().collect(Collectors.groupingBy(ScoreLineItem::getSettingId));
        for (EnterpriseExamScoreLineSetting setting : enterpriseExamScoreLineSettings) {
            EnterpriseScoreLineSaveParam enterpriseScoreLineSaveParam = new EnterpriseScoreLineSaveParam();
            enterpriseScoreLineSaveParam.setId(setting.getId());
            enterpriseScoreLineSaveParam.setExamId(setting.getExamId());
            enterpriseScoreLineSaveParam.setType(setting.getComposite());
            enterpriseScoreLineSaveParam.setDimension(setting.getDimension());

            List<ScoreLineItem> scoreDetailList = detailMap.get(setting.getId());
            if (CollectionUtils.isEmpty(scoreDetailList)) {
                continue;
            }

            for (ScoreLineItem settingDetail : scoreDetailList) {
                if (CommonEnums.SCORE_LINE_TYPE_1.getCode().equals(setting.getComposite())) {
                    enterpriseScoreLineSaveParam.setComparisonType(settingDetail.getComparisonType());
                    enterpriseScoreLineSaveParam.setCompositeScore(settingDetail.getScore());
                }
                if (CommonEnums.SCORE_LINE_TYPE_2.getCode().equals(setting.getComposite())) {
                    // 如果是是区间分数线,把总显示上去
                    enterpriseScoreLineSaveParam.setRegionName(settingDetail.getRegionName());
                    enterpriseScoreLineSaveParam.setRegionStartScore(settingDetail.getRegionStartScore());
                    enterpriseScoreLineSaveParam.setRegionEndScore(settingDetail.getRegionEndScore());
                }
            }


            if (StringUtils.isNotEmpty(subjectId) && CommonEnums.SCORE_LINE_DIMENSION_1.getCode().equals(dimension)) {
                scoreDetailList = scoreDetailList.stream().filter(item -> subjectId.equals(item.getSubjectId())).collect(Collectors.toList());
            }

            // 没有明细就不返回
            if (CollectionUtils.isNotEmpty(scoreDetailList)) {
                enterpriseScoreLineSaveParam.setScoreLineItems(scoreDetailList);
                result.add(enterpriseScoreLineSaveParam);
            }
        }
        return result;
    }

    /**
     * 得到分数线VO对象集合
     *
     * @param examId
     * @param dimension ""则查全部，0查考试，1查科目
     * @param subjectId
     * @return
     */
    @Override
    public EnterpriseScoreLineListParam getScoreLineVOList(String examId, String dimension, String subjectId) {
        EnterpriseScoreLineListParam result = new EnterpriseScoreLineListParam();

        List<EnterpriseScoreLineSaveParam> scoreLineList = getScoreLineList(examId, dimension, subjectId);
        if (CollectionUtils.isNotEmpty(scoreLineList)) {
            EnterpriseScoreLineSaveParam enterpriseScoreLineSaveParam = scoreLineList.get(0);
            List<ScoreLineItem> scoreLineItems = enterpriseScoreLineSaveParam.getScoreLineItems();
            List<String> subjectList = new ArrayList<>();
            List<String> examIdList = new ArrayList<>();
            for (ScoreLineItem scoreLineItem : scoreLineItems) {
                subjectList.add(scoreLineItem.getSubjectId());
                examIdList.add(scoreLineItem.getExamId());
            }
            result.setScoreLineData(scoreLineList);
            result.setDimension(enterpriseScoreLineSaveParam.getDimension());
            result.setExamId(enterpriseScoreLineSaveParam.getExamId());
            result.setType(enterpriseScoreLineSaveParam.getType());
            if (CommonEnums.SCORE_LINE_DIMENSION_2.getCode().equals(dimension)) {
                // 考试组的情况
                result.setSubjectList(examIdList);
            } else {
                result.setSubjectList(subjectList);
            }
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor = {RuntimeException.class})
    public void deleteScoreLineById(String id) {
        EnterpriseExamScoreLineSetting enterpriseExamScoreLineSetting = enterpriseExamScoreLineSettingMapper.selectEnterpriseExamScoreLineSettingById(id);

        if (null == enterpriseExamScoreLineSetting) {
            throw new CustomException("分数线不存在");
        }

        // 是否已归档
        iEnterpriseExamineeInfoService.checkExamineeArchived(enterpriseExamScoreLineSetting.getExamId());

        // 删除分数线
        enterpriseExamScoreLineSettingMapper.deleteEnterpriseExamScoreLineSettingById(id);

        //删除分数线明细
        enterpriseExamScoreLineSettingSubMapper.deleteEnterpriseExamScoreLineSettingSubBySettingId(id);
    }

    /**
     * 新增一种类型的分数线的时候删除其余类型
     *
     * @param enterpriseScoreLineSaveParam
     */
    private void deleteScoreLineByType(EnterpriseScoreLineSaveParam enterpriseScoreLineSaveParam) {
        EnterpriseExamScoreLineSetting queryParam = new EnterpriseExamScoreLineSetting();
        queryParam.setExamId(enterpriseScoreLineSaveParam.getExamId());
        List<EnterpriseExamScoreLineSetting> enterpriseExamScoreLineSettings = enterpriseExamScoreLineSettingMapper.selectEnterpriseExamScoreLineSettingList(queryParam);
        if (null == enterpriseExamScoreLineSettings) {
            return;
        }

        // 查询所有分数线明细
        List<ScoreLineItem> scoreDetailListAll = enterpriseExamScoreLineSettingSubMapper.selectEnterpriseExamScoreLineSettingByExamId(enterpriseScoreLineSaveParam.getExamId());
        Map<String, List<ScoreLineItem>> detailMap = scoreDetailListAll.stream().collect(Collectors.groupingBy(ScoreLineItem::getSettingId));
        for (EnterpriseExamScoreLineSetting item : enterpriseExamScoreLineSettings) {
            List<ScoreLineItem> scoreLineItems = detailMap.get(item.getId());
            if (item.getDimension().equals(enterpriseScoreLineSaveParam.getDimension()) && !item.getComposite().equals(enterpriseScoreLineSaveParam.getType())) {
                // 科目的
                if (CommonEnums.SCORE_LINE_DIMENSION_1.getCode().equals(enterpriseScoreLineSaveParam.getDimension())) {
                    if (!scoreLineItems.get(0).getSubjectId().equals(enterpriseScoreLineSaveParam.getScoreLineItems().get(0).getSubjectId())) {
                        continue;
                    }
                }

                // 删除分数线
                enterpriseExamScoreLineSettingMapper.deleteEnterpriseExamScoreLineSettingById(item.getId());
                //删除分数线明细
                enterpriseExamScoreLineSettingSubMapper.deleteEnterpriseExamScoreLineSettingSubBySettingId(item.getId());
            }
        }
    }

    @Override
    @Transactional(rollbackFor = {RuntimeException.class})
    public boolean deleteScoreLineBySubjectId(String subjectId) {
        EnterpriseExamScoreLineSettingSub query = new EnterpriseExamScoreLineSettingSub();
        query.setSubjectId(subjectId);

        // 需要删除包含这个科目的分数线
        List<EnterpriseExamScoreLineSettingSub> enterpriseExamScoreLineSettingSubs = enterpriseExamScoreLineSettingSubMapper.selectEnterpriseExamScoreLineSettingSubList(query);
        if (CollectionUtils.isEmpty(enterpriseExamScoreLineSettingSubs)) {
            return false;
        }

        // 删除明细
        enterpriseExamScoreLineSettingSubMapper.deleteEnterpriseExamScoreLineSettingSubBySubjectId(subjectId);

        // 明细数量，如果是1，删掉明细后就删除主表
        Map<String, Long> subjectMap = enterpriseExamScoreLineSettingSubs.stream().collect(Collectors
                .groupingBy(EnterpriseExamScoreLineSettingSub::getEnterpriseExamScoreLineSettingId, Collectors.counting()));
        for (Map.Entry<String, Long> entry : subjectMap.entrySet()) {
            if (null != entry.getValue() && entry.getValue() == 1L) {
                enterpriseExamScoreLineSettingMapper.deleteEnterpriseExamScoreLineSettingById(entry.getKey());
            }
        }
        return true;
    }

    @Override
    public List<String> selectScoreLineIds(String examId, String composite, String dimension) {
        EnterpriseExamScoreLineSetting scoreLineSetting = new EnterpriseExamScoreLineSetting();
        scoreLineSetting.setExamId(examId);
        scoreLineSetting.setComposite(composite);
        scoreLineSetting.setDimension(dimension);
        List<EnterpriseExamScoreLineSetting> scoreLineSettings = enterpriseExamScoreLineSettingMapper.selectEnterpriseExamScoreLineSettingList(scoreLineSetting);
        return scoreLineSettings.stream().map(EnterpriseExamScoreLineSetting::getId).collect(Collectors.toList());
    }

    @Override
    public List<String> selectScoreLineIds(String examId, String composite, String dimension, String subjectId) {
        List<EnterpriseScoreLineSaveParam> scoreLineList = iEnterpriseExamScoreLineSettingService.getScoreLineList(examId, dimension, subjectId);
        return scoreLineList.stream().map(item -> item.getId()).collect(Collectors.toList());
    }
}
